package com.shopping.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shopping.entity.Order;
import com.shopping.entity.Product;
import com.shopping.entity.User;
import com.shopping.entity.MemberLevelDiscount;
import com.shopping.exception.BusinessException;
import com.shopping.mapper.OrderMapper;
import com.shopping.service.OrderService;
import com.shopping.service.ProductService;
import com.shopping.service.UserService;
import com.shopping.service.MemberLevelDiscountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Isolation;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    private static final Logger log = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Resource
    private ProductService productService;

    @Resource
    private UserService userService;

    @Resource
    private MemberLevelDiscountService memberLevelDiscountService;

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public boolean createOrder(Order order) {
        try {
            log.info("开始创建订单: {}", order);

            // 验证商品是否存在
            Product product = productService.getById(order.getProductId());
            if (product == null) {
                log.error("创建订单失败: 商品不存在, productId={}", order.getProductId());
                throw new BusinessException("商品不存在");
            }
            log.info("商品验证通过: productId={}, name={}, price={}, stock={}",
                    product.getId(), product.getName(), product.getPrice(), product.getStock());

            // 验证用户是否存在
            User user = userService.getById(order.getUserId());
            if (user == null) {
                log.error("创建订单失败: 用户不存在, userId={}", order.getUserId());
                throw new BusinessException("用户不存在");
            }
            log.info("用户验证通过: userId={}, username={}, points={}",
                    user.getId(), user.getUsername(), user.getPoints());

            // 设置用户名
            order.setUsername(user.getUsername());
            log.info("设置订单用户名: {}", user.getUsername());

            // 折扣与生日特权逻辑
            java.math.BigDecimal discountRate = java.math.BigDecimal.ONE;
            boolean isBirthday = false;
            if (user.getBirthday() != null) {
                java.time.LocalDate today = java.time.LocalDate.now();
                isBirthday = today.getMonthValue() == user.getBirthday().getMonthValue() && today.getDayOfMonth() == user.getBirthday().getDayOfMonth();
            }
            if (isBirthday) {
                discountRate = new java.math.BigDecimal("0.80");
            } else {
                MemberLevelDiscount levelDiscount = memberLevelDiscountService.getOne(
                        new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<MemberLevelDiscount>().eq("level", user.getLevel().name())
                );
                if (levelDiscount != null) {
                    discountRate = levelDiscount.getDiscountRate();
                } else {
                    // 默认无折扣
                    discountRate = java.math.BigDecimal.ONE;
                }
            }

            // 检查库存
            if (product.getStock() < order.getQuantity()) {
                log.error("创建订单失败: 库存不足, productId={}, required={}, available={}",
                        order.getProductId(), order.getQuantity(), product.getStock());
                throw new BusinessException("库存不足");
            }
            log.info("库存检查通过: productId={}, required={}, available={}",
                    order.getProductId(), order.getQuantity(), product.getStock());

            // 生成订单号
            String orderNumber = generateOrderNumber();
            order.setOrderNumber(orderNumber);
            log.info("生成订单号: {}", orderNumber);

            // 计算订单总金额
            BigDecimal originalAmount = product.getPrice().multiply(BigDecimal.valueOf(order.getQuantity()));
            BigDecimal discountAmount = originalAmount.multiply(java.math.BigDecimal.ONE.subtract(discountRate)).setScale(2, java.math.RoundingMode.HALF_UP);
            BigDecimal totalAmount = originalAmount.subtract(discountAmount).setScale(2, java.math.RoundingMode.HALF_UP);
            order.setTotalAmount(totalAmount);
            order.setDiscountRate(discountRate);
            order.setDiscountAmount(discountAmount);
            log.info("计算订单金额: 原价={}, 折扣率={}, 优惠金额={}, 实付={}", originalAmount, discountRate, discountAmount, totalAmount);

            // 计算订单积分
            int orderPoints = product.getProductPoints() * order.getQuantity();
            int pointsAwarded = isBirthday ? orderPoints * 2 : orderPoints;
            order.setOrderPoints(orderPoints);
            order.setPointsAwarded(pointsAwarded);
            log.info("计算订单积分: 基础积分={}, 实际获得积分={}, 生日特权={}", orderPoints, pointsAwarded, isBirthday);

            // 设置订单时间
            order.setOrderDate(LocalDateTime.now());
            order.setOrderStatus(Order.OrderStatus.PENDING);
            log.info("设置订单状态为待付款");

            // 保存订单
            log.info("开始保存订单...");
            boolean saved = this.save(order);
            if (!saved) {
                log.error("订单保存失败");
                throw new BusinessException("订单保存失败");
            }
            log.info("订单保存成功: orderId={}", order.getId());

            // 更新商品库存
            log.info("开始更新商品库存...");
            boolean stockUpdated = productService.updateStock(order.getProductId(), order.getQuantity());
            if (!stockUpdated) {
                log.error("更新库存失败: productId={}, quantity={}", order.getProductId(), order.getQuantity());
                throw new BusinessException("更新库存失败");
            }
            log.info("库存更新成功: productId={}, quantity={}", order.getProductId(), order.getQuantity());

            // 更新用户积分
            log.info("开始更新用户积分...");
            boolean pointsUpdated = userService.updatePoints(order.getUserId(), pointsAwarded);
            if (!pointsUpdated) {
                log.error("更新用户积分失败: userId={}, points={}", order.getUserId(), pointsAwarded);
                throw new BusinessException("更新用户积分失败");
            }
            log.info("用户积分更新成功: userId={}, points={}", order.getUserId(), pointsAwarded);

            log.info("订单创建完成: orderId={}, orderNumber={}", order.getId(), order.getOrderNumber());
            return true;
        } catch (BusinessException e) {
            log.error("创建订单失败(业务异常): {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("创建订单失败(系统异常): ", e);
            throw new BusinessException("创建订单失败: " + e.getMessage());
        }
    }

    @Override
    public List<Order> getUserOrders(Long userId) {
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getUserId, userId)
                .orderByDesc(Order::getOrderDate);

        List<Order> orders = this.list(wrapper);

        // 填充用户和商品信息
        for (Order order : orders) {
            // 获取商品信息
            Product product = productService.getById(order.getProductId());
            if (product != null) {
                order.setProduct(product);
            }
        }

        return orders;
    }

    @Override
    @Transactional
    public boolean updateOrderStatus(Long orderId, Order.OrderStatus status) {
        Order order = this.getById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }

        order.setOrderStatus(status);
        return this.updateById(order);
    }

    @Override
    public Order getOrderDetail(Long orderId) {
        Order order = this.getById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }

        // 填充用户和商品信息
        order.setUser(userService.getById(order.getUserId()));
        order.setProduct(productService.getById(order.getProductId()));

        return order;
    }

    /**
     * 生成订单号
     */
    private String generateOrderNumber() {
        // 格式：ORD + 年月日时分秒 + 4位随机数
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String random = String.format("%04d", (int)(Math.random() * 10000));
        return "ORD" + timestamp + random;
    }

    /**
     * 分页获取订单列表
     */
    public Page<Order> getOrderList(int page, int size, Long userId, Order.OrderStatus status) {
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();

        if (userId != null) {
            wrapper.eq(Order::getUserId, userId);
        }
        if (status != null) {
            wrapper.eq(Order::getOrderStatus, status);
        }

        wrapper.orderByDesc(Order::getOrderDate);

        Page<Order> orderPage = new Page<>(page, size);
        Page<Order> result = this.page(orderPage, wrapper);

        // 填充用户和商品信息
        for (Order order : result.getRecords()) {
            // 获取商品信息
            Product product = productService.getById(order.getProductId());
            if (product != null) {
                order.setProduct(product);
            }
        }

        return result;
    }

    /**
     * 取消订单
     */
    @Transactional
    public boolean cancelOrder(Long orderId) {
        Order order = this.getById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }

        if (order.getOrderStatus() != Order.OrderStatus.PENDING) {
            throw new BusinessException("只能取消待付款的订单");
        }

        // 恢复库存
        productService.updateStock(order.getProductId(), -order.getQuantity());

        // 扣除用户积分
        userService.updatePoints(order.getUserId(), -order.getOrderPoints());

        // 更新订单状态
        order.setOrderStatus(Order.OrderStatus.CANCELLED);
        return this.updateById(order);
    }

    @Override
    public Page<Order> getOrderListForAdmin(Integer page, Integer size, String orderNumber, Long userId, Order.OrderStatus status) {
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();

        if (orderNumber != null && !orderNumber.trim().isEmpty()) {
            wrapper.like(Order::getOrderNumber, orderNumber);
        }
        if (userId != null) {
            wrapper.eq(Order::getUserId, userId);
        }
        if (status != null) {
            wrapper.eq(Order::getOrderStatus, status);
        }

        wrapper.orderByDesc(Order::getOrderDate);

        Page<Order> orderPage = new Page<>(page, size);
        Page<Order> result = this.page(orderPage, wrapper);

        // 填充用户和商品信息
        for (Order order : result.getRecords()) {
            order.setUser(userService.getById(order.getUserId()));
            order.setProduct(productService.getById(order.getProductId()));
        }

        return result;
    }

    @Override
    @Transactional
    public boolean updateOrderAddress(Long orderId, String address) {
        Order order = this.getById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }

        order.setAddress(address);
        return this.updateById(order);
    }

    @Override
    @Transactional
    public boolean shipOrder(Long orderId, Order.ShippingMethod shippingMethod) {
        Order order = this.getById(orderId);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }

        if (order.getOrderStatus() != Order.OrderStatus.PAID) {
            throw new BusinessException("只能对已付款的订单进行发货");
        }

        order.setOrderStatus(Order.OrderStatus.SHIPPED);
        if (shippingMethod != null) {
            order.setShippingMethod(shippingMethod);
        }
        return this.updateById(order);
    }

    @Override
    public List<Order> getLatestOrders(Integer limit) {
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(Order::getOrderDate)
                .last("LIMIT " + limit);

        List<Order> orders = this.list(wrapper);

        // 填充用户和商品信息
        for (Order order : orders) {
            order.setUser(userService.getById(order.getUserId()));
            order.setProduct(productService.getById(order.getProductId()));
        }

        return orders;
    }

    @Override
    public Object getOrderStatistics() {
        // 统计各种状态的订单数量
        LambdaQueryWrapper<Order> pendingWrapper = new LambdaQueryWrapper<>();
        pendingWrapper.eq(Order::getOrderStatus, Order.OrderStatus.PENDING);
        long pendingCount = this.count(pendingWrapper);

        LambdaQueryWrapper<Order> paidWrapper = new LambdaQueryWrapper<>();
        paidWrapper.eq(Order::getOrderStatus, Order.OrderStatus.PAID);
        long paidCount = this.count(paidWrapper);

        LambdaQueryWrapper<Order> shippedWrapper = new LambdaQueryWrapper<>();
        shippedWrapper.eq(Order::getOrderStatus, Order.OrderStatus.SHIPPED);
        long shippedCount = this.count(shippedWrapper);

        LambdaQueryWrapper<Order> completedWrapper = new LambdaQueryWrapper<>();
        completedWrapper.eq(Order::getOrderStatus, Order.OrderStatus.COMPLETED);
        long completedCount = this.count(completedWrapper);

        // 统计总订单数和总金额
        long totalOrders = this.count();

        LambdaQueryWrapper<Order> totalAmountWrapper = new LambdaQueryWrapper<>();
        totalAmountWrapper.select(Order::getTotalAmount);
        List<Order> orders = this.list(totalAmountWrapper);
        BigDecimal totalAmount = orders.stream()
                .map(Order::getTotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 计算平均订单金额
        BigDecimal avgOrderAmount = totalOrders > 0 ?
                totalAmount.divide(new BigDecimal(totalOrders), 2, RoundingMode.HALF_UP) :
                BigDecimal.ZERO;

        // 计算本月销售额
        LocalDateTime startOfMonth = LocalDateTime.now().withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
        LambdaQueryWrapper<Order> monthlyWrapper = new LambdaQueryWrapper<>();
        monthlyWrapper.ge(Order::getOrderDate, startOfMonth);
        List<Order> monthlyOrders = this.list(monthlyWrapper);
        BigDecimal monthlySales = monthlyOrders.stream()
                .map(Order::getTotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 计算今日新增订单数
        LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        long newOrders = this.count(new LambdaQueryWrapper<Order>()
                .ge(Order::getOrderDate, startOfDay));

        // 计算上月平均订单金额
        LocalDateTime startOfLastMonth = startOfMonth.minusMonths(1);
        LocalDateTime endOfLastMonth = startOfMonth.minusSeconds(1);
        LambdaQueryWrapper<Order> lastMonthWrapper = new LambdaQueryWrapper<>();
        lastMonthWrapper.between(Order::getOrderDate, startOfLastMonth, endOfLastMonth);
        List<Order> lastMonthOrders = this.list(lastMonthWrapper);
        BigDecimal lastMonthTotalAmount = lastMonthOrders.stream()
                .map(Order::getTotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal lastMonthAvgOrderAmount = lastMonthOrders.isEmpty() ?
                BigDecimal.ZERO :
                lastMonthTotalAmount.divide(new BigDecimal(lastMonthOrders.size()), 2, RoundingMode.HALF_UP);

        // 计算平均订单金额变化率
        double orderAmountChange = lastMonthAvgOrderAmount.compareTo(BigDecimal.ZERO) > 0 ?
                ((avgOrderAmount.subtract(lastMonthAvgOrderAmount)).divide(lastMonthAvgOrderAmount, 4, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal("100")).doubleValue()) : 0;

        // 计算总积分发放
        LambdaQueryWrapper<Order> pointsWrapper = new LambdaQueryWrapper<>();
        pointsWrapper.select(Order::getOrderPoints);
        List<Order> pointsOrders = this.list(pointsWrapper);
        long totalPoints = pointsOrders.stream()
                .mapToLong(Order::getOrderPoints)
                .sum();

        // 计算本月积分发放
        long monthlyPoints = monthlyOrders.stream()
                .mapToLong(Order::getOrderPoints)
                .sum();

        // 创建统计结果Map
        Map<String, Object> statistics = new java.util.HashMap<>();
        statistics.put("pendingOrders", pendingCount);
        statistics.put("paidOrders", paidCount);
        statistics.put("shippedOrders", shippedCount);
        statistics.put("completedOrders", completedCount);
        statistics.put("totalOrders", totalOrders);
        statistics.put("newOrders", newOrders);
        statistics.put("totalSales", totalAmount);
        statistics.put("avgOrderAmount", avgOrderAmount);
        statistics.put("orderAmountChange", orderAmountChange);
        statistics.put("monthlySales", monthlySales);
        statistics.put("totalPoints", totalPoints);
        statistics.put("monthlyPoints", monthlyPoints);

        return statistics;
    }
}